package org.zcode.generator.core.generator.clazz;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.zcode.generator.core.config.BeanTypeConfig;
import org.zcode.generator.core.config.ImportConfig;
import org.zcode.generator.core.config.XmlConfig;
import org.zcode.generator.core.generator.ClazzCreator;
import org.zcode.generator.core.generator.method.AtomMethodCreator;
import org.zcode.generator.core.util.GeneratorUtil;

/**
 * @Description:
 * @author zhoulk
 * @date: 2019/10/28
 */
public class AtomServiceCreator extends ClazzCreator {
    private String tableRemarks;
    private Interface atomApiService;
    private TopLevelClass atomControllerClass;
    private String tableName;

    public AtomServiceCreator(XmlConfig xmlConfig,
                              BeanTypeConfig beanTypeConfig,
                              IntrospectedTable introspectedTable) {
        super(xmlConfig, beanTypeConfig, introspectedTable);
        this.methodCreator = new AtomMethodCreator(xmlConfig, beanTypeConfig, introspectedTable);
        this.tableRemarks = GeneratorUtil.getTableRemarks(introspectedTable.getRemarks());
        String table = introspectedTable.getBaseRecordType();
        this.tableName = table.substring(table.lastIndexOf(".") + 1).substring(xmlConfig.substring);
        init();
    }

    @Override
    protected void init() {
        FullyQualifiedJavaType atomApiServiceType = new FullyQualifiedJavaType(xmlConfig.atomServicePack + ".I" + tableName + "ApiService");
        atomApiService = new Interface(atomApiServiceType);
        atomApiService.addJavaDocLine(GeneratorUtil.getDocTmpl(tableRemarks + "原子服务API接口", xmlConfig.author));
        FullyQualifiedJavaType atomControllerType = new FullyQualifiedJavaType(xmlConfig.atomControllerPack + "." + tableName + "Controller");
        atomControllerClass = new TopLevelClass(atomControllerType);
        atomControllerClass.addSuperInterface(atomApiServiceType);
        atomControllerClass.addJavaDocLine(GeneratorUtil.getDocTmpl(tableRemarks + "原子服务API接口实现", xmlConfig.author));
        addField(atomControllerClass);
        addImport();
    }
    
    @Override
    public GeneratedJavaFile createInterface() {
        atomApiService.setVisibility(JavaVisibility.PUBLIC);
        atomApiService.addAnnotation("@Api(value = \"" + tableRemarks + "原子服务API接口\", description = \"" + tableRemarks + "原子服务API接口\")");
        atomApiService.addAnnotation("@RequestMapping(value = \"/" + GeneratorUtil.toLowerCase(tableName) + "\")");

        Method method;
        if (introspectedTable.getPrimaryKeyColumns() != null && introspectedTable.getPrimaryKeyColumns().size() > 0) {
            method = methodCreator.qryByIdMethod(tableName, 1);
            if (method != null) {
                method.removeAllBodyLines();
                atomApiService.addMethod(method);
            }
        }
        method = methodCreator.countMethod(tableName, 1);
        method.removeAllBodyLines();
        atomApiService.addMethod(method);

        method = methodCreator.qrysMethod(tableName, 1);
        method.removeAllBodyLines();
        atomApiService.addMethod(method);

        method = methodCreator.updMethod(tableName, 1);
        method.removeAllBodyLines();
        atomApiService.addMethod(method);

        method = methodCreator.addMethod(tableName, 1);
        method.removeAllBodyLines();
        atomApiService.addMethod(method);

        return new GeneratedJavaFile(atomApiService, xmlConfig.atomTargetProject);
    }

    @Override
    public GeneratedJavaFile createClazz() {
        atomControllerClass.setVisibility(JavaVisibility.PUBLIC);
        atomControllerClass.addAnnotation("@RestController");
        Method method;
        if (introspectedTable.getPrimaryKeyColumns() != null && introspectedTable.getPrimaryKeyColumns().size() > 0) {
            method = methodCreator.qryByIdMethod(tableName, 0);
            if (method != null) {
                method.addAnnotation("@Override");
                atomControllerClass.addMethod(method);
            }
        }
        method = methodCreator.countMethod(tableName, 0);
        method.addAnnotation("@Override");
        atomControllerClass.addMethod(method);

        method = methodCreator.qrysMethod(tableName, 0);
        method.addAnnotation("@Override");
        atomControllerClass.addMethod(method);

        method = methodCreator.updMethod(tableName, 0);
        method.addAnnotation("@Override");
        atomControllerClass.addMethod(method);

        method = methodCreator.addMethod(tableName, 0);
        method.addAnnotation("@Override");
        atomControllerClass.addMethod(method);
        
        return new GeneratedJavaFile(atomControllerClass, xmlConfig.atomTargetProject);
    }

    @Override
    protected void addField(TopLevelClass topLevelClass) {
        Field field = new Field();
        field.setName(GeneratorUtil.toLowerCase(beanTypeConfig.interfaceType.getShortName())); // 设置变量名
        field.setType(beanTypeConfig.interfaceType); // 类型
        field.setVisibility(JavaVisibility.PRIVATE);
        field.addAnnotation("@Autowired");
        topLevelClass.addField(field);
    }

    @Override
    protected void addImport() {
        atomApiService.addImportedType(beanTypeConfig.updIPoType);
        atomApiService.addImportedType(beanTypeConfig.qrysIPoType);
        atomApiService.addImportedType(beanTypeConfig.qryOPoType);
        atomApiService.addImportedType(beanTypeConfig.qrysOPoType);
        atomApiService.addImportedType(beanTypeConfig.addIPoType);
        atomApiService.addImportedType(ImportConfig.listType);
        atomApiService.addImportedType(ImportConfig.requestMapping);
        atomApiService.addImportedType(ImportConfig.requestBody);
        atomApiService.addImportedType(ImportConfig.apiType);
        atomApiService.addImportedType(ImportConfig.apiOperation);
        atomApiService.addImportedType(ImportConfig.pathVariable);
        atomApiService.addImportedType(ImportConfig.requestMethod);

        atomControllerClass.addImportedType(beanTypeConfig.updIPoType);
        atomControllerClass.addImportedType(beanTypeConfig.qrysIPoType);
        atomControllerClass.addImportedType(beanTypeConfig.qryOPoType);
        atomControllerClass.addImportedType(beanTypeConfig.qrysOPoType);
        atomControllerClass.addImportedType(beanTypeConfig.addIPoType);
        atomControllerClass.addImportedType(ImportConfig.listType);
        atomControllerClass.addImportedType(atomApiService.getType());
        atomControllerClass.addImportedType(ImportConfig.restController);
        atomControllerClass.addImportedType(ImportConfig.requestBody);
        atomControllerClass.addImportedType(ImportConfig.pathVariable);
        atomControllerClass.addImportedType(beanTypeConfig.interfaceType);
        atomControllerClass.addImportedType(ImportConfig.autowired);
        atomControllerClass.addImportedType(beanTypeConfig.pojoType);
        atomControllerClass.addImportedType(beanTypeConfig.pojoConditionType);
        atomControllerClass.addImportedType(ImportConfig.beanCovertor);
    }
}
